{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Linking Plots Using Brush Interval Selector"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Details on how to use the brush interval selector can be found in [this](../Interactions/Selectors.ipynb#brushselectors) notebook.\n",
    "\n",
    "Brush interval selectors can be used where *continuous updates* are **not** desirable (for example, in callbacks performing slower computations)\n",
    "\n",
    "The boolean trait `brushing` can be used to control *continuous updates* in the `BrushSelector`. `brushing` will be set to `False` when the interval selector is not brushing. We can register callbacks by listening to the `brushing` trait of the brush selector. We can check the value of `brushing` trait in the callback and perform updates *only* at the end of brushing.\n",
    "\n",
    "Let's now look at an example of linking a time series plot to a scatter plot using a `BrushIntervalSelector`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ipywidgets import Layout, HTML, VBox\n",
    "import bqplot.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's set up an interval selector on a figure containing two time series plots. The interval selector can be activated by clicking on the figure"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from bqplot.interacts import BrushIntervalSelector\n",
    "\n",
    "y1, y2 = np.random.randn(2, 200).cumsum(axis=1) # two simple random walks\n",
    "\n",
    "fig_layout = Layout(width='900px', height='500px')\n",
    "time_series_fig = plt.figure(layout=fig_layout)\n",
    "line = plt.plot([y1, y2])\n",
    "\n",
    "# create a fast interval selector by passing in the X scale and the line mark on which the selector operates\n",
    "intsel = BrushIntervalSelector(marks=[line], scale=line.scales['x'])\n",
    "time_series_fig.interaction = intsel # set the interval selector on the figure"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's now create a scatter plot of the two time series and stack it below the time series plot using a `VBox`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scat_fig = plt.figure(layout=fig_layout, \n",
    "                      animation_duration=750,\n",
    "                      title='Scatter of time series slice selected by the interval selector')\n",
    "# set the x and y attributes to the y values of line.y\n",
    "scat = plt.scatter(*line.y, colors=['red'], stroke='black') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# define a callback for the interval selector\n",
    "def update_scatter(*args):\n",
    "    brushing = intsel.brushing\n",
    "    \n",
    "    # update scatter *only* when the interval selector\n",
    "    # is not brushing to prevent continuous updates\n",
    "    if not brushing:\n",
    "        # interval selector is active\n",
    "        if line.selected is not None:\n",
    "            # get the start and end indices of the interval\n",
    "            start_ix, end_ix = line.selected[0], line.selected[-1]\n",
    "        else:  # interval selector is *not* active\n",
    "            start_ix, end_ix = 0, -1\n",
    "            \n",
    "        #update the x and y attributes of the scatter by slicing line.y\n",
    "        with scat.hold_sync():\n",
    "            scat.x, scat.y = line.y[:, start_ix:end_ix]\n",
    "\n",
    "# register the callback with brushing trait of interval selector\n",
    "intsel.observe(update_scatter, 'brushing')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "help_label = HTML('<div style=\"color: blue; font-size: 16px; margin:20px 0px 0px 50px\">\\\n",
    "                  Brush on the time series plot to activate the interval selector</div>')\n",
    "VBox([help_label, time_series_fig, scat_fig])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
